grammar ArkcubeScript;

@lexer::members {
public static readonly NEWLINE = 1;
public static readonly COMMENTS = 2;
}

program: stat* EOF;

stat
    : importStat ';'                        # ImportStatement
    | viewStat ';'                          # ViewStatement
    | variableDecl ';'                      # VariableDeclStatement
    | functionDecl ';'                      # FunctionDeclStatement
    | (ifStat | whileStat) ';'              # ControlStatement
    | returnStat ';'                        # ReturnStatement
    | expr ';'                              # ExprStatement
    ;

importStat
    : Import name = StringLiteral As alias = Identifier                         # ModuleAlias
    | From name = StringLiteral Import mod = Identifier                         # ModuleSymbol
    | From name = StringLiteral Import mod = Identifier As alias = Identifier   # ModuleSymbolAlias
    | From name = StringLiteral Import '*'                                      # ModuleAllSymbol
    ;

viewStat: cellViewStat | cellEXViewStat | cellDBViewStat;
cellViewStat: CellView '(' arguments ')' ';' block End;
cellEXViewStat: CellEXView '(' arguments ')' ';' block End;
cellDBViewStat: CellDBView '(' arguments ')' ';' block End;


variableDecl: type Identifier ('=' expr)?;
type
    : Identifier '[' ']'      # ArrayType
    | Identifier              # SimpleType
    ;

functionDecl: type Function Identifier '(' (parameterList)? ')' ';' block End;

parameterList: parameter (',' parameter)*;

parameter: type Identifier;

block: stat*;

ifStat: If '(' expr ')' ';' stat* (Elseif '(' expr ')' ';' stat*)*  (Else ';' stat*)? End;

whileStat: While '(' expr ')' ';' stat* End;

returnStat: Return expr;

// 冒号运算符外层是大括号{‘01月’:'12月'}，表示ELEMENT_ARRAY
// 冒号运算符外层是方括号或圆括号[‘期间’:'12月']、SUM(‘期间’:'12月')，表示维度声明
expr
    : Number                                                            # Number
    | StringLiteral                                                     # StringLiteral
    | BooleanLiteral                                                    # BooleanLiteral
    | Identifier                                                        # Name
    | expr '[' expr ']'                                                 # ArrayIndex
    | expr '.' Identifier                                               # MemberRange
    | dim ':' expr                                                      # DimColon
    | '{' arguments '}'                                                 # MemberSet
    | left = expr op = '^' right = expr                                 # PowerLike
    | op = ('+'|'-'|'~') right = expr                                   # PrefixExpression
    | left = expr op = ('*'|'/'|'\\') right = expr                      # MultiplyLike
    | left = expr op = ('+'|'-') right = expr                           # PlusLike
    | left = expr op = '|' right = expr                                 # ListLike
    | left = expr op = ('='|'<>'|'>'|'>='|'<'|'<='|'@='|'@<>'|'@>'|'@>='|'@<'|'@<=') right = expr   # CompareLike
    | left = expr op = ('%'|'&') right = expr                           # LogicLike
    | '(' expr ')'                                                      # PriorityExpression
    | functionCall                                                      # FunctionApply
    | Identifier '.' functionCall                                       # DotFunctionApply
;

functionCall: Identifier '(' arguments? ')';
arguments: expr (',' expr)*;

dim: Identifier | StringLiteral;

Number                              : Integer ('.' Digit+)?;
StringLiteral                       : Str1 | Str2;
BooleanLiteral                      : 'true' | 'false';


CellDBView                          : C E L L D B V I E W;
CellEXView                          : C E L L E X V I E W;
CellView                            : C E L L V I E W;
Function                            : F U N C T I O N;
Import                              : I M P O R T;
As                                  : A S;
From                                : F R O M;
End                                 : E N D;
If                                  : I F;
Elseif                              : E L S E I F;
Else                                : E L S E;
While                               : W H I L E;
Return                              : R E T U R N;
Plus                                : '+';      // 正号和加号
Minus                               : '-';      // 负号和减号
Star                                : '*';      // 乘
Div                                 : '/';      // 除
Div2                                : '\\';     // 除，除0得0
Caret                               : '^';      // 幂，注意tabase的幂运算是左结合
Or                                  : '|';      // 字符拼接
Comma                               : ',';      // 逗号
Dot                                 : '.';      // 点
Colon                               : ':';      // 冒号
Sharp                               : '#';      // 注释
Not                                 : '!';      // 反向引用
And                                 : '&';      // 且
Percent                             : '%';      // 或
Tilde                               : '~';      // 非
Equal                               : '=';      // 赋值和等于
NotEqual                            : '<>';     // 不等于
Greater                             : '>';      // 大于
GreaterEqual                        : '>=';     // 大于等于
Less                                : '<';      // 小于
LessEqual                           : '<=';     // 小于等于
StrEqual                            : '@=';     // 文本相等
StrNotEqual                         : '@<>';     // 文本不等于
StrGreater                          : '@>';      // 文本大于
StrGreaterEqual                     : '@>=';     // 文本大于等于
StrLess                             : '@<';      // 文本小于
StrLessEqual                        : '@<=';     // 文本小于等于
Feed                                : '=>';     // Feeder
SingleQuote                         : '\'';     // 单引号
Semi                                : ';';      // 分号
LeftParen                           : '(';      // 左括号
RightParen                          : ')';      // 右括号
LeftBracket                         : '[';      // 左方括号
RightBracket                        : ']';      // 右方括号
LeftBrace                           : '{';      // 左大括号
RightBrace                          : '}';      // 右大括号

fragment Str1    : '"' SChar* '"';
fragment Str2    : '\'' SChar2* '\'';
fragment SChar   :   ~["] | '\\"';
fragment SChar2  :   ~['] | '\\\'';
fragment Integer : Zero+ | [1-9] Digit*;
fragment Digit   : Zero | [1-9];
fragment Zero    : [0];

fragment A : [aA];
fragment B : [bB];
fragment C : [cC];
fragment D : [dD];
fragment E : [eE];
fragment F : [fF];
fragment G : [gG];
fragment H : [hH];
fragment I : [iI];
fragment J : [jJ];
fragment K : [kK];
fragment L : [lL];
fragment M : [mM];
fragment N : [nN];
fragment O : [oO];
fragment P : [pP];
fragment Q : [qQ];
fragment R : [rR];
fragment S : [sS];
fragment T : [tT];
fragment U : [uU];
fragment V : [vV];
fragment W : [wW];
fragment X : [xX];
fragment Y : [yY];
fragment Z : [zZ];

Identifier                          : ~[ .%^=()&[\]'*@:,{}\\"!><|+\-?;/~\r\n\t]+;

NewLine             : ('\r'? '\n' | '\r')+ -> channel(1);
WhiteSpace          : [ \t\p{Z}]+ -> skip;
LineComment         : '#' .*? '\n' -> channel(2);
